package cc.loach.homekit.app.homekit.settings;

import android.content.Context;
import android.content.SharedPreferences;

import java.net.NetworkInterface;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import cc.loach.homekit.app.homekit.settings.database.HapDatabaseImpl;
import cc.loach.homekit.hap.framewok.HapSettings;
import cc.loach.homekit.hap.framewok.HapDatabase;
import cc.loach.homekit.hap.typedef.setup.SetupHash;
import cc.loach.homekit.hap.typedef.setup.SetupId;
import cc.loach.homekit.hap.typedef.setup.SetupPayload;
import cc.loach.homekit.hap.typedef.spec.AccessoryCategoryIdentifier;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;

public class HapSettingsImpl implements HapSettings {

    private static final String TAG = HapSettingsImpl.class.getSimpleName();
    private final Logger logger = LoggerFactory.getLogger(TAG);
    private static final String NAME = "Hap";
    private final SharedPreferences preferences;
    private final HapDatabase database;
    private final AccessoryCategoryIdentifier categoryIdentifier = AccessoryCategoryIdentifier.Bridges;
    private String deviceId;
    private String name;
    private String modelName;
    private String setupId;
    private String setupCode;
    private String setupHash;
    private String setupPayload;

    public HapSettingsImpl(Context context) {
        this.preferences = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        this.database = new HapDatabaseImpl(context);
        this.initialize();
    }

    private void initialize() {
        deviceId = preferences.getString("deviceId", null);
        if (deviceId == null) {
            deviceId = getMacAddress();
            if (deviceId == null) {
                deviceId = generateId();
                logger.info("generateId: " + deviceId);
            } else {
                logger.info("getMacAddress: " + deviceId);
            }

            // 保存一下ID，因为ID有可能是随机生成的，保证下次启动时的ID是同一个ID。
            preferences.edit().putString("deviceId", deviceId).apply();
        }

        name = "homepad";
        modelName = android.os.Build.MODEL;

        setupId = preferences.getString("setupId", null);
        if (setupId == null) {
            setupId = SetupId.generate();
            preferences.edit().putString("setupId", setupId).apply();
        }

        setupCode = preferences.getString("setupCode", null);
        if (setupCode == null) {
            setupCode = "031-45-154";
            preferences.edit().putString("setupCode", setupCode).apply();
        }

        setupHash = preferences.getString("setupHash", null);
        if (setupHash == null) {
            setupHash = SetupHash.generate(setupId, deviceId);
            preferences.edit().putString("setupHash", setupHash).apply();
        }

        setupPayload = preferences.getString("setupPayload", null);
        if (setupPayload == null) {
            setupPayload = SetupPayload.generate0(categoryIdentifier, setupCode, setupId);
            preferences.edit().putString("setupPayload", setupPayload).apply();
        }

        logger.info("id: " + deviceId);
        logger.info("name: " + name);
        logger.info("model: " + modelName);
        logger.info("SetupId: " + setupId);
        logger.info("SetupCode: " + setupCode);
        logger.info("SetupHash: " + setupHash);
        logger.info("SetupPayload: " + setupPayload);
    }

    @Override
    public String deviceId() {
        return deviceId;
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public String modelName() {
        return modelName;
    }

    @Override
    public String serialNumber() {
        return deviceId.replace(":", "");
    }

    @Override
    public AccessoryCategoryIdentifier categoryIdentifier() {
        return categoryIdentifier;
    }

    @Override
    public String setupId() {
        return setupId;
    }

    @Override
    public String setupCode() {
        return setupCode;
    }

    @Override
    public String setupHash() {
        return setupHash;
    }

    @Override
    public String setupPayload() {
        return setupPayload;
    }

    @Override
    public HapDatabase database() {
        return database;
    }

//    /**
//     * 这个不靠谱，有些设备取不到真的MAC地址
//     */
//    private String getWiFiMacAddress(Context context) {
//        try {
//            WifiManager manager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
//            return manager.getConnectionInfo().getMacAddress().toUpperCase();
//        } catch (Exception e) {
//            return null;
//        }
//    }

    /**
     * 可以取到Mac地址
     */
    private String getMacAddress() {
        try {
            List<NetworkInterface> networkInterfaceList = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface networkInterface : networkInterfaceList) {
                byte[] macBytes = networkInterface.getHardwareAddress();
                if (macBytes != null) {
                    StringBuilder macAddressBuilder = new StringBuilder();
                    for (byte b : macBytes) {
                        macAddressBuilder.append(String.format("%02X:", b));
                    }

                    if (macAddressBuilder.length() > 0) {
                        macAddressBuilder.deleteCharAt(macAddressBuilder.length() - 1);
                    }

                    return macAddressBuilder.toString().toUpperCase();
                }
            }

            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private String generateId() {
        String[] array = new String[6];

        for (int i = 0; i < 6; ++i) {
            Random random = new Random();
            int value = random.nextInt();
            array[i] = String.format("%02X", value);
        }

        return String.join(":", array);
    }
}
